﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;

namespace DBMock
{
    /// <summary>
    /// DBMock
    /// </summary>
    public class DBMock
    {
        /// <summary>
        /// 数据库连接
        /// </summary>
        public string ConString { get; private set; }

        /// <summary>
        /// 表builder集合
        /// </summary>
        public List<TableBuilder> Builders { get; private set; }

        /// <summary>
        /// 单次批量操作最大值
        /// </summary>
        public int BulkSize { get; private set; }

        /// <summary>
        /// copy开始
        /// </summary>
        public event EventHandler<CopyEventArgs> StartCopy;

        /// <summary>
        /// copy结束
        /// </summary>
        public event EventHandler<CopyEventArgs> EndCopy;

        /// <summary>
        /// 初始化MockData
        /// </summary>
        /// <param name="conString">SQL Server连接</param>
        /// <param name="type">实体类型</param>
        /// <param name="totalCount">实体总数</param>
        public DBMock(string conString, Type type, int totalCount, int bulkSize = 300000)
            : this(conString, new Dictionary<Type, int> { { type, totalCount } }, bulkSize)
        {

        }

        /// <summary>
        /// 初始化MockData
        /// </summary>
        /// <param name="conString">SQL Server连接</param>
        /// <param name="source">源字典，key：实体类型，value：实体总数</param>
        public DBMock(string conString, Dictionary<Type, int> source, int bulkSize = 300000)
        {
            if (conString == null || source == null)
            { throw new ArgumentNullException(); }

            BulkSize = bulkSize;
            ConString = conString;

            Builders = SplitSource(source)
                .Select(s => new TableBuilder(s.Key, s.Value))
                .ToList();
        }

        /// <summary>
        /// 写数据表到数据库
        /// </summary>
        public void Mock()
        {
            if (string.IsNullOrEmpty(ConString) || Builders == null)
                return;

            foreach (var builder in Builders)
            {
                using (var connection = new SqlConnection(ConString))
                {
                    connection.Open();

                    if (builder == null)
                        continue;

                    var dt = builder.Build();
                    var copier = DBHelper.GetBulkCopier(connection, dt);

                    var eArgs = new CopyEventArgs(copier);
                    StartCopy?.Invoke(this, eArgs);

                    copier.WriteToServer(dt);

                    EndCopy?.Invoke(this, eArgs);
                }
            }
        }

        //分割源数据
        private List<KeyValuePair<Type, int>> SplitSource(Dictionary<Type, int> source)
        {
            var results = new List<KeyValuePair<Type, int>>();

            foreach (var pair in source)
            {
                var outcome = pair.Value / BulkSize;
                var remainder = pair.Value % BulkSize;

                for (int i = 0; i < outcome; i++)
                { results.Add(new KeyValuePair<Type, int>(pair.Key, BulkSize)); }

                if (remainder != 0)
                { results.Add(new KeyValuePair<Type, int>(pair.Key, remainder)); }
            }

            return results;
        }
    }

    /// <summary>
    /// building事件参数
    /// </summary>
    public class BuildingEventArgs : EventArgs
    {
        /// <summary>
        /// 表builder
        /// </summary>
        public TableBuilder Builder { get; private set; }

        /// <summary>
        /// 初始化BuildingEventArgs
        /// </summary>
        /// <param name="builder"></param>
        public BuildingEventArgs(TableBuilder builder)
        {
            Builder = builder;
        }
    }

    /// <summary>
    /// copy参数集
    /// </summary>
    public class CopyEventArgs : EventArgs
    {
        public SqlBulkCopy Copier { get; private set; }

        public CopyEventArgs(SqlBulkCopy copier)
        {
            Copier = copier;
        }
    }
}
